<script setup>
import { ref, toRefs, reactive, computed, onBeforeMount } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import StringOrNumber from '../components/StringOrNumber.vue';
import CreateOrEditFrame from '../components/CreateOrEditFrame.vue';
import { listHandler } from '../../api/Generic'
import { deleteTableRow, object2List, list2Object  } from '../../utils/utils';
import Table from '../components/Table.vue';
import DialogYaml from '../components/DialogYaml.vue'
import { obj2Yaml } from '../../utils/utils';
import { createIngressHandler as createHandler, updateIngressHandler as updateHandler, getIngressClassListHandler } from '../../api/ingress.js'
import { getServiceListHandler } from '../../api/service';
import { useRouter } from 'vue-router'
import { getSecretListHandler } from '../../api/secret';
const router = useRouter()
const props = defineProps({
  method: {
    type: String,
    default: 'Create'
  },
  item: {
    type: Object
  }
})
const data = reactive({
  clusterId: '',
  namespace: '',
  item: {// service数据结构定义
    apiVersion: 'networking.k8s.io/v1',
    kind: 'Ingress',
    metadata: {
      name: '',
      namespace: '',
      labels: {},
      annotations: {},
    },
    spec: {
      rules: []
    }
  },
  path: {
    path: '',
    pathType: 'Prefix',
    backend: {
      service: {
        name: '',
        port: {
          // name: '',
          number: ''
        }
      }
    }
  },
  options: {
    ingressClassList: [],
    tlsSecretList: [],
    serviceList: [], // 请求控制器接口返回的数据
    serviceSelected: [], // 初始值设置为undefined或者'' 解决el-select placeholder不显示bug
    labelList: [],
    annotationList: [],
    rules:{
      name: [
        {required: true, message: 'ingress名称必须值', trigger: 'blur'}
      ],
      path: [
        {required: true, message: '路径必须填写', trigger:'blur'},
        {pattern: '^(?=/)', message: '路径必须以/开头', trigger: 'blur'}
      ],
      serviceName: [
        {required: true, message: '后端service名称必须值', trigger:'blur'}
      ],
      servicePort: [
        {required: true, message: '后端端口必须值', trigger:'blur'}
      ],

    },
    pathType: [
      {
        label: '精确匹配',
        value: 'Exact'
      },
      {
        label: '前缀匹配',
        value: 'Prefix'
      },
      {
        label: '取决于IngressClass',
        value: 'ImplementationSpecific'
      },
    ]
  }
})
const itemRef = ref()
const activeName = ref('basic')
const labelConfig = ref('labels')
const yamlContent = ref('')
const showDetail = ref(false)

const submitRollback = (msg) => {
  ElMessageBox.confirm(
    msg,
    '执行结果',
    {
      confirmButtonText: '查看列表',
      cancelButtonText: '返回',
      type: 'success',
      draggable: true,
    }
  ).then(() => {
    // 跳转/service/list
    router.replace({
      path: '/ingress/list',
      query: {
        clusterId: data.clusterId,
        namespace: data.namespace
      }
    })
  }).catch(() => {
    return
  })
}
const submitHandler = (tag) => {
  data.item.metadata.labels = list2Object(data.options.labelList)
  data.item.metadata.annotations = list2Object(data.options.annotationList)

  if(tag == 'yaml') { // json转yaml
    const yamlData = obj2Yaml(data.item)
    yamlContent.value = yamlData
    showDetail.value = true
  } else {
    const postData = {
      clusterId: data.clusterId,
      namespace: data.namespace,
      item: data.item
    }
    if (props.method != 'Update') {
      createHandler(postData).then((response) => {
        submitRollback(response.data.message)
      })
    } else {
      updateHandler(postData).then((response) => {
        console.log(props.method)
        submitRollback(response.data.message)
      })
    }
  }
}
const submit = (tag) => {
  itemRef.value.validate((valid) => {
    if(!valid){
      ElMessage({
        message: '请完善表单',
        type: "warning"
      })
    }else {
      submitHandler(tag)
    }
  })
  

}
const namespaceChangedHandler = (clusterId, namespace) => {
  console.log('service namespaceChangedHandler', clusterId, namespace)
  data.clusterId = clusterId
  data.namespace = namespace
  data.item.metadata.namespace = namespace
  getServiceList()// 刷新ingress资源列表

}

const getServiceList = async () => {
  console.log("获取资源列表：", data.clusterId, data.namespace)
  await getServiceListHandler({clusterId: data.clusterId, namespace: data.namespace}).then((res)=>{
    console.log("获取到的资源列表:", res.data.data.items)
    data.options.serviceList = res.data.data.items
  })
}


const ingressClassVisibleChanged = (visible) => {
  if (!visible) { return }
  const getListParas = {
    clusterId: data.clusterId
  }
  getIngressClassListHandler(getListParas).then((res) => {
    data.options.ingressClassList = res.data.data.items
  })
}

// 添加端口
const addRule = () => {
  const rule = {
    host: '',
    http: {
      paths: [
        JSON.parse(JSON.stringify(data.path))
      ]
    }
  }
  data.item.spec.rules.push(JSON.parse(JSON.stringify(rule)))
}
const addPath = (ruleIndex) => {
  data.item.spec.rules[ruleIndex].http.paths.push(JSON.parse(JSON.stringify(data.path))) 
}

const getServicePort = computed(() =>(serviceName) => {
  console.log("获取当前service的端口配置:",serviceName)
  for (let s=0;s<data.options.serviceList.length; s++){
    if(data.options.serviceList[s].metadata.name == serviceName){
      const ports = []
      data.options.serviceList[s].spec.ports.forEach((port)=> {
        if (ports.indexOf(port.port == -1)) {
          ports.push(port.port)
        }
      })
      return ports
    }
  }
})

// 获取TLS类型的secret
const getTLSSecretList = (visible)=>{
  console.log("visible:",visible)
  if (visible) {// 展开的时候去查询items
    // 调用查询列表的函数
    const getData = {
      clusterId: data.clusterId,
      namespace: data.namespace,
      labelSelector: '',
      fieldSelector: 'type=kubernetes.io/tls'
    }
    getSecretListHandler(getData).then(
      (res) => {
        data.options.tlsSecretList = res.data.data.items
        console.log(data.options.tlsSecretList)
      }
    )
  }
}

const addTls = () => {
  console.log("添加tls")
  if( data.item.spec.tls == undefined){
    data.item.spec.tls = []
  }
  const tlsConfig = {
    hosts: [],
    secretName: ''
  }
  data.item.spec.tls.push(tlsConfig)
}

onBeforeMount(() => {
  if(props.method != 'Create'){
    data.item = JSON.parse(JSON.stringify(props.item))
    data.options.labelList = object2List(data.item.metadata.labels)
    data.options.annotationList = object2List(data.item.metadata.annotations)
    data.item.spec.rules.forEach((rule) => {
      rule.http.paths.forEach((path) => {
        if (data.options.serviceSelected.indexOf(path.backend.service.name) == -1){
          data.options.serviceSelected.push(path.backend.service.name)
        }
      })
    })
  }
})

const { options, item, clusterId, namespace } = toRefs(data)
</script>

<template>
  <CreateOrEditFrame
  :namespace-readonly="props.method=='Update'"
  :cluster-readonly="props.method=='Update'"
  @namespace-chanaged-rollback="namespaceChangedHandler"
  >
  <!-- 头部插入内容 -->
    <template #header>
      <!-- 选择资源名称 -->
      <el-select
      style="margin-left: 10px; width: 180px;"
      v-model="options.serviceSelected"
      value-key="metadata.name"
      multiple collapse-tags
      placeholder="选择代理的service"
      >
        <el-option
        v-for="t in options.serviceList"
        :key="t.metadata.name"
        :label="t.metadata.name"
        :value="t.metadata.name"
        >
        </el-option>
      </el-select>
    </template>
    <template #main>
      <el-form :model="item"
      center
      ref="itemRef"
      >
        <el-tabs v-model="activeName" class="demo-tabs">
          <el-tab-pane label="基本配置" name="basic" style="height:360px">
            <el-row :gutter="20">
              <el-col :span="6">
                <el-form-item :rules="options.rules.name" label="Ingress名称" prop="metadata.name" required>
                  <el-input :disabled="props.method =='Update'" v-model="item.metadata.name" style="margin-left: 10px; width: 180px;"></el-input>
                </el-form-item>
              </el-col>

              <!-- 选择ingressClassName -->
              <el-col :span="4">
                <el-form-item label="选择IngressClass" prop="">
                  <el-select @visible-change="ingressClassVisibleChanged" clearable v-model="item.spec.ingressClassName" placeholder="请选择IngressClass">
                      <el-option v-for="s in options.ingressClassList" :key="s.metadata.name" :label="s.metadata.name" :value="s.metadata.name">
                      </el-option>
                  </el-select>
                </el-form-item>
              </el-col>
            </el-row>
          </el-tab-pane>



          <el-tab-pane label="路由配置">
            <el-tabs tab-position="left">
              <el-tab-pane label="域名配置">
                <!-- 第一个table 展示配置域名 -->
                <el-table :data="item.spec.rules" border height="360">
                  <el-table-column prop="host" label="域名" width="240" align="center">
                    <template #default="scope">
                      <el-input v-model="scope.row.host" placeholder="请输入域名"></el-input>
                    </template>
                  </el-table-column>

                  <el-table-column prop="http" label="路径配置" align="center">
                    <template #default="scope">
                      <el-table :data="scope.row.http.paths" border height="120">
                        <el-table-column prop="path" label="路径" align="center">
                          <template #default="pathScope">
                            <el-form-item :rules="options.rules.path" required :prop="('spec.rules.'+scope.$index+'.http.paths.'+pathScope.$index+'.path')">
                              <el-input v-model="pathScope.row.path" placeholder="请输入路径"></el-input>
                            </el-form-item>
                          </template>
                        </el-table-column>


                        <el-table-column prop="backend.service.name" label="后端服务" width="240" align="center">
                          <template #default="pathScope">
                            <el-form-item :rules="options.rules.serviceName" required :prop="('spec.rules.'+scope.$index+'.http.paths.'+pathScope.$index+'.backend.service.name')">
                              <el-select v-model="pathScope.row.backend.service.name" placeholder="选择代理服务">
                                <el-option v-for="s in options.serviceSelected" :key="s" :label="s" :value="s"></el-option>
                              </el-select>
                            </el-form-item>
                          </template>
                        </el-table-column>


                        <el-table-column prop="backend.service.port.number" label="后端端口" width="180" align="center">
                          <template #default="pathScope">
                            <el-form-item :rules="options.rules.servicePort" required :prop="('spec.rules.'+scope.$index+'.http.paths.'+pathScope.$index+'.backend.service.port.number')">
                              <el-select v-model="pathScope.row.backend.service.port.number" placeholder="选择后端端口">
                                <el-option v-for="p in getServicePort(pathScope.row.backend.service.name)" :key="p" :label="p" :value="p"></el-option>
                              </el-select>
                            </el-form-item>
                          </template>
                        </el-table-column>


                        <el-table-column prop="pathType" label="匹配模式" width="180" align="center">
                          <template #default="pathScope">
                            <el-select v-model="pathScope.row.pathType" placeholder="选择路由匹配模式">
                              <el-option v-for="pt in options.pathType" :key="pt.value" :label="pt.label" :value="pt.value"></el-option>
                            </el-select>
                          </template>
                        </el-table-column>
                        

                        <el-table-column width="140" align="center" fixed="right">
                          <template #header>
                            <el-button type="primary" link @click="addPath(scope.$index)">添加</el-button>
                          </template>
                          <template #default="pathScope">
                            <el-button type="warning" link @click="deleteTableRow(item.spec.rules[scope.$index].http.paths, pathScope.$index)">删除</el-button>
                          </template>
                        </el-table-column>
                      </el-table>
                    </template>
                  </el-table-column>


                  <el-table-column width="140" align="center" fixed="right">
                    <template #header>
                      <el-button type="primary" link @click="addRule()">添加</el-button>
                    </template>
                    <template #default="scope">
                      <el-button type="warning" link @click="deleteTableRow(item.spec.rules, scope.$index)">删除</el-button>
                    </template>
                  </el-table-column>
                </el-table>
              </el-tab-pane>

              <el-tab-pane label="证书配置" name="https">
                <el-table :data="item.spec.tls" border height="360">
                  <el-table-column prop="" label="域名" align="center">
                    <template #default="scope">
                      <el-select multiple filterable v-model="scope.row.hosts" placeholder="选择域名">
                          <el-option v-for="s in item.spec.rules" :key="s.host" :label="s.host" :value="s.host "></el-option>
                      </el-select>
                    </template>
                  </el-table-column>
                  <el-table-column prop="" label="证书" align="center">
                    <template #default="scope">
                      <el-select @visible-change="getTLSSecretList" v-model="scope.row.secretName" placeholder="选择证书">
                          <el-option v-for="s in options.tlsSecretList" :key="s.metadata.name" :label="s.metadata.name" :value="s.metadata.name "></el-option>
                      </el-select>
                    </template>
                  </el-table-column>S

                  

                  <el-table-column width="140" align="center" fixed="right">
                    <template #header>
                      <el-button type="primary" link @click="addTls()">添加</el-button>
                    </template>
                    <template #default="scope">
                      <el-button type="warning" link @click="deleteTableRow(item.spec.tls, scope.$index)">删除</el-button>
                    </template>
                  </el-table-column>
                </el-table>
              </el-tab-pane>
            </el-tabs>
          </el-tab-pane>



          <el-tab-pane label="注释及标签" name="labels" style="height:360px">
            <el-tabs v-model="labelConfig" tabPosition="left">
              <el-tab-pane label="ingress标签配置" name="labels">
                <Table :list="options.labelList"></Table>
              </el-tab-pane>
              <el-tab-pane label="ingress注解配置" name="annos">
                <Table :list="options.annotationList"></Table>
              </el-tab-pane>
            </el-tabs>
          </el-tab-pane>
        </el-tabs>
        <span style="display: block;margin-top: 30px;" class="span-button">
          <el-button @click="submit('yaml')">yaml</el-button>
          <el-button type="primary" @click="submit()">{{ props.method=="Update"?"更新":"创建" }}</el-button>
        </span>
      </el-form>
    </template>
  </CreateOrEditFrame>
  <DialogYaml
  :cluster-id="clusterId"
  :namespace="namespace"
  :yaml-content="yamlContent"
  :show-dialog="showDetail"
  @close-dialog-handler="(val) => { showDetail = val }"
  >
  </DialogYaml>
</template>

<style scoped>
</style>
